#ifndef _EVENT_DRIVER_H_
#define _EVENT_DRIVER_H_

//#include <string>
#include <map>
#include <list>
#include <vector>
#include <queue>
#include <boost/cstdint.hpp>
#include <boost/thread.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>

namespace auroral { namespace event {

using namespace std;
using namespace boost;

class EventDriver;

// define EVENT_HANDLE : the event handle type.
// the data is passed with @data.
// @data might be F_NULL for some event.
// return  0 means EventDriver will continue to run the next handle for this event.
// return -1 means the process for this event should stop. 
typedef int (* EVENT_HANDLE )(EventDriver &eventDriver, string eventType, shared_ptr<void> data);

struct HANDLE_INFO
{
	HANDLE_INFO()
		:priority(0), handle(NULL) 
	{

	};
	bool operator==(const HANDLE_INFO &other)
	{
		return (handle==other.handle && priority == other.priority);
	}
	int32_t priority;
	EVENT_HANDLE handle;
};

struct EVENT_INFO
{
	std::string eventType;
	shared_ptr<void> data;	
};

class EventDriver:public noncopyable
{
	
	// handle the handles and run the event loop
public:
	EventDriver();
	virtual ~EventDriver();
	
	// register a event type of the name @eventType
	// return -1 when failed
	// return 1 when duplicated
	virtual int registerEvent(string eventType);

	// unregister the event event of the name @eventType.
	// return -1 when failed.
	// return 1 when the event of the name @eventType does not exist.
	virtual int unregisterEvent(string eventType);

	// add a handle named @handle to the event type @eventType, with a defined priority.
	// the smaller the priority is, the earlier the handle will be executed when the event of the event type happened.
	// return -1 when failed.
	// return  0 when success.
	virtual int addHandle(string eventType, EVENT_HANDLE handle, int32_t priority = 0);

	// remove a handle named @handle of the event type @eventType.
	// the @handle==F_NULL, all the handles of the event @event will be removed.
	// return -1 when failed.
	// return  0 when success.
	virtual int removeHandle(string eventType, EVENT_HANDLE handle = NULL, int32_t priority = 0);

	// emit a event of event type: @eventType, with a pointer @data.
	// the memory @data pointer will be in the charge of EventDriver.
	// EventDriver must call delete on @data when finished all the handle.
	// This method must be implemented to be thread-safe.
	// return -1 when error.
	virtual int emitEvent(string eventType, shared_ptr<void> data = shared_ptr<void>());

	// run the event loop.
	// return 0 when event loop quited by quit().
	// return -1 when error.
	virtual int exec();

	// process one event from the event queue.
	virtual void processOnce();
	
	// make the event loop to quit.
	virtual void quit();

	// exit the event loop with the return value: @value
	virtual void exit(int value);
protected:
	virtual void pushEvent(string eventType, shared_ptr<void> data);
	virtual EVENT_INFO popEvent();
private:
	typedef list<HANDLE_INFO>								HandleList;
	typedef map<string, HandleList>							HandleMap;
	typedef queue<EVENT_INFO>								EventQueue;
	HandleMap								handleMap;
	EventQueue								eventQueue;
	mutex									mutex_;
	bool									running;
	int										returnValue;

};

} }; // namespace auroral::event


#endif // _EVENT_DRIVER_H_
